#include "rose_subprocess.h"

typedef struct rose_chain
{
	char **argv;
	struct rose_chain *next;
} rose_chain;

int rose_spawn_pipe_chain_base(rose_chain *cmd, int input)
{
	int fds[2] = {-1, -1};

	if (cmd->next != NULL)
	{
		pipe(fds);
	}

	pid_t f;
	if ((f = fork()) == 0)
	{
		if (input != -1)
		{
			dup2(input, STDIN_FILENO);
			close(input);
		}

		if (fds[1] != -1)
		{
			dup2(fds[1], STDOUT_FILENO);
			close(fds[1]);
		}

		if (fds[0] != -1)
		{
			close(fds[0]);
		}

		execvp(cmd->argv[0], cmd->argv);
		_exit(1);
	}
	else
	{
		if (input != -1)
		{
			close(input);
		}

		if (fds[1] != -1)
		{
			close(fds[1]);
		}

		if (cmd->next != NULL)
		{
			return rose_spawn_pipe_chain_base(cmd->next, fds[0]);
		}
		else
		{
			return f;
		}
	}
}

int rose_spawn_pipe_chain(char ***argv, int n)
{
	rose_chain *buf = (rose_chain *)malloc(sizeof(rose_chain)*n);
	for (int i = 0; i < n; i++)
	{
		buf[i].argv = argv[i];
		if (i < n-1)
			buf[i].next = buf+i+1;
		else
			buf[i].next = NULL;
	}

	return rose_spawn_pipe_chain_base(buf, -1);
}

int rose_spawn_pipe(char **argv, int pin, int pout)
{
	pid_t f;
	if ((f = fork()) == 0)
	{
		if (pin != -1)
		{
			dup2(pin, STDIN_FILENO);
			close(pin);
		}

		if (pout != -1)
		{
			dup2(pout, STDOUT_FILENO);
			close(pout);
		}
		
		execvp(argv[0], argv);
		_exit(1);
	}
	else
	{
		if (pin != -1)
			close(pin);
		if (pout != -1)
			close(pout);

		return f;
	}
}

int rose_wait(int pid)
{
	int e = 0;
	waitpid(pid, &e, 0);
	return e;
}

int rose_wait_chain(int n, int pid)
{
	for (int i = 0; i < n-1; i++)
		wait(NULL);
	return rose_wait(pid);
}

